export namespace Coolcar {
    // export const serverAddr = "http://127.0.0.1:8080"
    export const serverAddr = "https://wq.1flove.com"
    // export const wsAddr = "ws://127.0.0.1:9090"
    export const wsAddr = "ws://122.112.138.106:9090"
    const AUTH_ERR = "AUTH_ERR"

    // @ts-ignore
    interface RequestOption<REQ, any> {
        method: 'GET' | 'PUT' | 'POST' | 'DELETE',
        path: string,
        data?: REQ
    }

    const tokenData = {
        token: '',
        expiryMs: 0
    }

    export interface AuthOption {
        attachAuthHeader: boolean,
        retryOnAuthErr: boolean
    }

    export async function sendRequestWithAuthRetry(o: RequestOption<any, any>, a?: AuthOption): Promise<any> {
        const authOpt = a || {
            attachAuthHeader: true,
            retryOnAuthErr: true
        }

        try {
            await login()
            return sendRequest(o, authOpt)
        } catch (err) {
            if (err === AUTH_ERR && authOpt.retryOnAuthErr) {
                tokenData.token = ''
                tokenData.expiryMs = 0
                return sendRequestWithAuthRetry(o, {
                    attachAuthHeader: authOpt.attachAuthHeader,
                    retryOnAuthErr: false
                })
            } else {
                throw err
            }
        }
    }

    export async function login() {
        if (tokenData.token && tokenData.expiryMs >= Date.now()) {
            return
        }
        const wxResp = await wxLogin()
        const reqTimeMs = Date.now()
        const resp = await sendRequest({
            method: "POST",
            path: "/v1/auth/login",
            data: {
                code: wxResp.code
            },
        }, {
            attachAuthHeader: false,
            retryOnAuthErr: false
        })
        tokenData.token = resp.access_token!
        tokenData.expiryMs = reqTimeMs + resp.expires_in * 1000!
    }

    function sendRequest(o: RequestOption<any, any>, a: AuthOption): Promise<any> {
        const authOpt = a || {
            attachAuthHeader: true
        }
        return new Promise((resolve, reject) => {
            const header: Record<any, any> = {}

            if (authOpt.attachAuthHeader) {
                if (tokenData.token && tokenData.expiryMs >= Date.now()) {
                    header.authorization = `Bearer ${tokenData.token}`
                } else {
                    reject(AUTH_ERR)
                    return
                }
            }
            wx.request({
                url: serverAddr + o.path,
                method: o.method,
                data: o.data,
                header,
                success: res => {
                    if (res.statusCode == 401) {
                        reject(AUTH_ERR)
                    } else if (res.statusCode >= 400) {
                        reject(res)
                    } else {
                        resolve(res.data)
                    }
                },
                fail: reject
            })
        })
    }

    function wxLogin(): Promise<WechatMiniprogram.LoginSuccessCallbackResult> {
        return new Promise((resolve, reject) => {
            wx.login({
                success: resolve,
                fail: reject
            })
        })
    }

    export interface UploadFilePots {
        localPath: string
        url: string
    }

    export function uploadFile(o: UploadFilePots): Promise<void> {
        const data = wx.getFileSystemManager().readFileSync(o.localPath)

        return new Promise((resolve, reject) => {
            wx.request({
                url: o.url,
                data,
                method: 'PUT',
                success: res => {
                    if (res.statusCode >= 400) {
                        reject(res)
                    } else {
                        resolve()
                    }
                },
                fail: reject
            })
        })
    }
}